PowerTCP Emulation for .NET
Designed for Modern Applications



PowerTCP Emulation for .NET exposes a modern multi-threaded design with technical advantages over competing products.


Async Methods

The async methods (BeginXXX) seen in competing products reflect an antiquated single-threaded design model that denies the benefits of multi-threaded power. Please read on to see how PowerTCP Emulation for .NET delivers multi-threaded power to your application without adding the complexity that is often associated with multi-threading techniques.

Operation on the client side of the client/server model is inherently command driven, so Emulation for .NET provides a simple Start(delegate) method that executes the body of your delegate on a worker thread. This straight-forward concept provides a flexible technique for using PowerTCP in any application environment.

This design eliminates the need for BeginXXX methods and EndXXX events. There is a clean interface with one method for each function and several advantages are immediately realized:

Efficiency. Methods are designed to efficiently block on socket receive operations (the thread sleeps until bytes are received). This results in the most robust and efficient design possible.

Reusable code. Your delegate(s) can be used in applications both with and without a UI. It is no longer necessary to use BeginFoo for Windows Forms applications, and (the blocking) Foo for services, web applications and console applications.

Lower life-cycle cost. Code is written sequentially because there is no UI message pump to consider. It is not necessary to write code for numerous event handlers. Your code is self-documenting, easier to debug and maintain, and has a lower life-cycle cost.

Easy-to-implement parallel operation. Worker threads are easily spawned, supporting intensively parallel operations. Alternatively, serial operation is easily implemented by using just one thread. Flexibility of design is key.

No more state machine. It is not necessary to track state in event handlers. Take the simple case where the following sequence takes place:

Using BeginXXX, an event is raised when data is received and a state machine is required (if R1 is received then send S1, else if R2 is received then send S2). Using a single worker thread, the operation is coded in simple, declarative steps (Receive R1, Send S1, Receive R2, Send S2).


No More Pseudo-Blocking

Competing products use "pseudo-blocking" to process UI events while the method blocks. Without pseudo-blocking overhead methods are faster and more efficient. Also, re-entrancy problems (caused when UI messages are processes while a communication method is in progress) are no longer possible.


Developing Applications Without a UI

Developing console applications, web applications, services and other applications without a UI is as easy as ever. Sequential code performs efficiently. If parallel operation is desired, Start(delegate) can be used to execute code in any delegate body in parallel.


Developing Applications With a UI

Developing Windows Forms applications is now just as easy as writing applications without a UI. One method (the delegate) can be used in both types of applications. The only difference is that a UI app uses Start(delegate) to spawn a worker thread upon which the method executes, and any data needed by the UI must be marshaled to the UI thread. To this end, PowerTCP components include Start() and Marshal() convenience methods.


The Start Method

Use the Start method to execute one or more functions on a new worker thread, so the UI is not blocked during operation. The syntax for this method is simple (C# and VB code snippets follow):

C#
Copy Code
telnet1.Start(myBlockingFunction, myObject); //Can also be called without passing an object

private void myBlockingFunction(object myObject)
{
   ...
}
Visual Basic
Copy Code
telnet1.Start(AddressOf myBlockingFunction, myObject)  'Can also be called without passing an object

Private Sub myBlockingFunction(ByVal myObject As Object)
   ...
End Sub

Marshaling Data

It is often necessary to pass information from a worker thread to update an element on the UI thread. Use the Marshal method for this purpose. Each Marshal overload is paired with an event that is raised on the UI thread. For example (C# and VB code snippets follow):

C#
Copy Code
//Read data, marshal to the UI thread
byte [] buffer = new byte [1024];
telnet1.Marshal(telnet1.Read(buffer), "", null);

private void telnet1_Data(object sender, DataEventArgs e)
{
    //Display received data
    //This event is raised on the UI thread
    displayData(e.Data);
}
Visual Basic
Copy Code
'Read data, marshal to the UI thread
Dim buffer(1023) As Byte
telnet1.Marshal(telnet1.Read(buffer), "", Nothing)

Private Sub telnet1_Data(ByVal sender As Object, ByVal e As DataEventArgs)
    'Display received data
    'This event is raised on the UI thread
    displayData(e.Data)
End Sub

Typical Use

The developer wants to execute a series of functions without interfering with the user-interface. A button, textbox, and the PowerTCP component are added to the form. Pressing the button will initiate a telnet session with communication displayed in the textbox. The automateSession function, which can be reused in a non-UI application, is passed to Start and executes on a worker thread (C# and VB code snippets follow).

C#
Copy Code
private void button1_Click(object sender, EventArgs e)
{
    //Event handlers were added in the designer
    //Start the process on a worker thread so the UI is not blocked
    telnet1.Start(automateSession, null);
}

private void automateSession(object notUsed)
{
    //This function executes on a worker thread
    try
    {
        //Connect
        telnet1.Connect("myServer");

        //Login to the server, marshal data to the UI thread
        Data data = telnet1.Login(new Credentials("myUsername", "myPassword", "$"));
        telnet1.Marshal(data, "", null);


        //Send a list command
        telnet1.Write("ls -la\r");//Wait for prompt, marshal data to the UI thread
        telnet1.Marshal(telnet1.ReadToDelimiter("$"), "", null);

        //Send an exit command; server will close the connection
        telnet1.Write("exit\r");

        //Read any remaining data before the shutdown
        telnet1.Marshal(telnet1.ReadToEnd(), "", null);
    }
    catch (Exception ex)
    {
        //Report errors to the UI thread
        telnet1.Marshal(ex);
    }
}

private void telnet1_Data(object sender, DataEventArgs e)
{
    //Add data received to the textbox
    textBox1.AppendText(e.Data.ToString());
}

private void telnet1_Error(object sender, ErrorEventArgs e)
{
    //Add error messages to the textbox
    textBox1.AppendText(e.GetException().Message);
}

private void telnet1_StateChanged(object sender, EventArgs e)
{
    //Change appearance of textbox when connected
    textBox1.BackColor = (telnet.State == ConnectionState.Closed)
        ? SystemColors.ControlDark 
        : SystemColors.ControlLight;
}
Visual Basic
Copy Code
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs)
    'Event handlers were added in the designer
    'Start the process on a worker thread so the UI is not blocked
    telnet1.Start(AddressOf automateSession, Nothing)
End Sub

Private Sub automateSession(ByVal notUsed As Object)
    'This function executes on a worker thread
    Try
        'Connect
        telnet1.Connect("myServer")

        'Login to the server, marshal data to the UI thread
        Dim data As Data = telnet1.Login(New Credentials("myUsername", "myPassword", "$"))
        telnet1.Marshal(data, "", Nothing)

        'Send a list command
        telnet1.Write("ls -la" & vbCr) 'Wait for prompt, marshal data to the UI thread
        telnet1.Marshal(telnet1.ReadToDelimiter("$"), "", Nothing)

        'Send an exit command; server will close the connection
        telnet1.Write("exit" & vbCr)

        'Read any remaining data before the shutdown
        telnet1.Marshal(telnet1.ReadToEnd(), "", Nothing)
    Catch ex As Exception
        'Report errors to the UI thread
        telnet1.Marshal(ex)
    End Try
End Sub

Private Sub telnet1_Data(ByVal sender As Object, ByVal e As DataEventArgs)
    'Add data received to the textbox
    textBox1.AppendText(e.Data.ToString())
End Sub

Private Sub telnet1_Error(ByVal sender As Object, ByVal e As ErrorEventArgs)
    'Add error messages to the textbox
    textBox1.AppendText(e.GetException().Message)
End Sub

Private Sub telnet1_StateChanged(ByVal sender As Object, ByVal e As EventArgs) Handles telnet1.StateChanged
    'Change appearance of textbox when connected
    If (telnet1.State = ConnectionState.Closed) Then
        textBox1.BackColor = SystemColors.ControlDark
    Else
        textBox1.BackColor = SystemColors.ControlLight
    End If
End Sub

In the second example, the developer wants to receive data whenever it is available, but again, without interfering with the ongoing processes of the application. Event handlers (not shown) are implemented as in the first example (C# and VB code snippets follow).

C#
Copy Code
private void button1_Click(object sender, EventArgs e)
{
   //Start the process on a worker thread (no state info passed in)
   telnet1.Start(receiveData, null);
}

private void receiveData(object notUsed)
{
   //This function executes on a worker thread
   try
   {
       //Connect to the server, marshal data to the UI thread
       telnet1.Connect("myServer");

       //Receive data when it is sent by the remote host
       byte[] buffer = new byte[1024];
       while (telnet1.State == ConnectionState.Connected)
           telnet1.Marshal(telnet1.Read(buffer), "", null);
   }
   catch (Exception ex)
   {
       //Report errors to the UI thread
       telnet1.Marshal(ex);
   }
}
Visual Basic
Copy Code
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles button1.Click
   'Start the process on a worker thread (no state info passed in)
   telnet1.Start(AddressOf receiveData, Nothing)
End Sub

Private Sub receiveData(ByVal notUsed As Object)
   'This function executes on a worker thread
   Try
      'Connect and login to the server, marshal data to the UI thread
      telnet1.Connect("myServer")

      'Receive data when it is sent by the remote host
      Dim buffer() As Byte = New Byte(1023){}
      Do While telnet.State = ConnectionState.Connected
         telnet1.Marshal(telnet1.Read(buffer), "", Nothing)
      Loop
   Catch ex As Exception
      'Report errors to the UI thread
      telnet1.Marshal(ex)
   End Try
End Sub

See Also

PowerTCP Emulation for .NET Documentation Version 4.7
© 2018 Dart Communications. All Rights Reserved.
Send comments on this topic